/*
	Copyright 2009 Jason Nottingham

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.


    How to submit a patch:
    1. create or modify a test case (under 'tests') so that it fails to compile/link/run without 
       your change
    2. verify you have the latest sources (resync/merge)
    3. fix or add the missing functionality
    4. verify that your changes fixes the newly broken test case in #1 - it now builds and runs 
       C++ the same as the original C#
    5. create a Subversion-friendly diff or patch file of your changes (including the test cases)
    6. submit your patch at http://gonative.codeplex.com


*/

#pragma once

#include "BasicDataTypes.h"

#define DialogResult	DWORD


typedef int  (*OnClickHandlerCallback)();
typedef void (*OnBoolCallback)();


class MessageBox
{
public:
	static int Show( HWND hWnd, string text )
	{
		return ::MessageBox( hWnd, text.ToString(), L"", MB_OK );
	}
	static int Show( string text )
	{
		return ::MessageBox( NULL, text.ToString(), L"", MB_OK );
	}
	static int Show( HWND hWnd, WCHAR *text )
	{
		return ::MessageBox( hWnd, text, L"", MB_OK );
	}
	static int Show( WCHAR *text )
	{
		return ::MessageBox( NULL, text, L"", MB_OK );
	}
	static int Show( HWND hWnd, string text, string title )
	{
		return ::MessageBox( hWnd, text.ToString(), title.ToString(), MB_OK );
	}
	static int Show( string text, string title )
	{
		return ::MessageBox( NULL, text.ToString(), title.ToString(), MB_OK );
	}
	static int Show( HWND hWnd, WCHAR *text, WCHAR *title )
	{
		return ::MessageBox( hWnd, text, title, MB_OK );
	}
	static int Show( WCHAR *text, WCHAR *title )
	{
		return ::MessageBox( NULL, text, title, MB_OK );
	}
};


class Container
{
public:
	void Dispose()
	{
	}

};

#define IContainer Container


enum
{
    PropertyEnabled,
    PropertyVisible
};

class Color
{
public:
	Color() {}
};


class SizeF
{
public:
	SizeF() {}
	SizeF( float x, float y)
	{
	}

};

class Point
{
public:
	Point() {}
	int X,Y;

	Point( int x, int y )
	{
		X = x;
		Y = y;
	}
};

class Size
{
public:
	Size() {}
	int X,Y;
	Size( int x, int y )
	{
		X = x;
		Y = y;
	}
};

class EventHandler
{
private:
    OnClickHandlerCallback onClick;

public:
    EventHandler( OnClickHandlerCallback callBack )
    {
        onClick = callBack;
    }

    int OnClick()
    {
        return onClick();
    }

};


class PropertyParent
{
public:
    virtual void OnNewValue( DWORD propertyEnum, int i ) {}
};



class BoolProperty
{
private:
    DWORD       propertyEnum;
    PropertyParent*  thisParent;
    bool        value;

public:
    BoolProperty()
    {
        value = false;
    }

    void Initialize( DWORD dwPropertyEnum, void* This )
    {
        propertyEnum = dwPropertyEnum;
        thisParent = (PropertyParent*)This;
        value = false;
    }

    inline bool operator = (const bool b )
    {
        value = b;
        thisParent->OnNewValue( propertyEnum, (int)b );
		return value;
    }

};




class UIControl : public PropertyParent
{
public:
    UIControl()
	{
        hWnd = NULL;
        Enabled.Initialize( PropertyEnabled, this );
        Visible.Initialize( PropertyVisible, this );
	}

    virtual WCHAR *GetClassName() { return L"UndefinedControl"; }
    virtual DWORD GetWindowStyles() { return 0; }

    BoolProperty    Enabled;
	BoolProperty    Visible;

	Point	Location;
	Size	Size;
	int		TabIndex;
	string	Name;
	string	Text;
	DWORD	dwControlID;


    void OnNewValue( DWORD dwProperty, int i )
    {
        switch( dwProperty )
        {
            case PropertyEnabled:
                EnableWindow( hWnd, (i!=0) );
                break;
            case PropertyVisible:
                ShowWindow( hWnd, (i==0) ? SW_HIDE : SW_SHOW );
                break;
        }
    }

    void CreateControl( HWND hParent, HINSTANCE hInstance )
    {
        if ( hWnd )
            DestroyWindow( hWnd );

        hWnd = CreateWindow( GetClassName(), Text.ToString(), WS_CHILD|WS_VISIBLE|GetWindowStyles(), 
                    Location.X, Location.Y, Size.X, Size.Y, hParent, (HMENU)dwControlID, hInstance, NULL );

        if ( hWnd == NULL )
            Debug::WriteLine( string( "Create window failed with GLE = " ) + string((int)GetLastError()) );
    }

private:
    HWND    hWnd;

};




class Button : public UIControl
{
public:
	Button()
	{
	}

    WCHAR *GetClassName() { return L"BUTTON"; }

    DWORD GetWindowStyles()
    {
        //return BS_PUSHBUTTON|WS_TABSTOP;
        return BS_PUSHBUTTON|WS_TABSTOP|BS_FLAT;
    }

	BOOL				UseVisualStyleBackColor;	
	List<EventHandler>	Click;

};

class ListBox : public UIControl
{
public:
	ListBox() {}

    WCHAR *GetClassName() { return L"LISTBOX"; }
};

class EventArgs
{
};


class MouseEventArgs
{
};

class KeyEventArgs
{
	DWORD dwKeyCode;

public:
	DWORD KeyCode() { return dwKeyCode; };
};


class ColumnHeader
{
public:
	ColumnHeader() {}
};


class Label : public UIControl
{
public:
	Label() {}

    WCHAR *GetClassName() { return L"LABEL"; }
};


class ListView : public UIControl
{
public:
	ListView() {}

    WCHAR *GetClassName() { return L"LISTVIEW"; }

};


class ProgressBar : public UIControl
{
public:
	ProgressBar() {}

    WCHAR *GetClassName() { return L"PROGRESSBAR"; }
};


class RichTextBox : public UIControl
{
public:
	RichTextBox() {}

    WCHAR *GetClassName() { return L"RICHTEXT20"; }
};


class TextBox : public UIControl
{
public:
	TextBox() {}

    WCHAR *GetClassName() { return L"EDIT"; }
};


class Brush
{
};


class Font
{
};


class Pen
{
};


class Rectangle
{
};


class Timer
{
private:
    HWND    hwnd;
public:
	DWORD   dwTickID;
	DWORD	Interval;
	
	void Start( HWND hWnd )
	{
        hwnd = hWnd;
        BOOL b = SetTimer( hwnd, dwTickID, Interval, NULL );
        if ( b )
            Debug::WriteLine( string("SetTimer returns ") + (int)b );
	}

	void Stop()
	{
        KillTimer( hwnd, dwTickID );
	}
};




class Form
{
public:
	Form()
	{
	}

	DialogResult	DialogResult;

	Color	TextColor;
	Color	BackgroundColor;
	SizeF	AutoScaleDimensions;
	Size	ClientSize;

	int		Left, Right, Height, Width;
	string	Name;
	string	Text;

	List<UIControl>	Controls;

	void Close()
	{
		assert( hWnd );
		assert( IsWindow( hWnd ) );
        DestroyWindow( hWnd );
		hWnd = NULL;
	}

	HACCEL Accelerators()
	{
		return NULL;
	}

	void SuspendLayout() {}
    void PerformLayout() {}
	void ResumeLayout( BOOL b )
	{
	}

    void CreateChildren()
    {
		// iterate through the child controls, creating their windows
        UIControl *control;
        Controls.start_iteration(); 
		while( control = Controls.get_next() )
		{
            string debug = string("[") + control->Name + "] [" + control->Text + "] [";
            debug += string(control->GetClassName()) + "]\n";
			Debug::WriteLine( debug );
            control->CreateControl( hWnd, hInstance );
		}
    }

	void Dispose() {}

	void OnCreate( HWND hWnd ) {}
	void OnSize() {}
	void OnTimer( WPARAM wParam, LPARAM lParam ) {}
	void OnCommand( WPARAM wParam, LPARAM lParam ) {}
	void OnActivate() {}
	void OnPaint() {}
	void OnDestroy() {}

	HWND		hWnd;
    HINSTANCE   hInstance;
};


class ColorDialog
{
public:
	int ShowDialog( Form parent )
	{
		return MessageBox( NULL, L"implement ColorDialog!", L"BUGBUG", MB_OK );
	}
};




class Application
{
public:
	static void EnableVisualStyles()
	{
	}

	static void SetCompatibleTextRenderingDefault( BOOL b )
	{
	}

	static void Run( Form *form )
	{
	}

};


class MenuStrip
{
public:
    void SuspendLayout() {}
    void PerformLayout() {}
	void ResumeLayout( BOOL b )
	{
	}

};

class ToolStripMenuItem
{
};

